package com.practice.nettyhandler;

import com.practice.model.EventSyncHostTime;
import com.practice.util.ProtocolUtil;

import org.greenrobot.eventbus.EventBus;

import java.util.List;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

public class EchoClientHandler extends ByteToMessageDecoder {
    Long x1;
    Long x2;
    Long y1;
    Long y2;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(Unpooled.copiedBuffer(ProtocolUtil.TIME_FRAME));
        x1 = System.currentTimeMillis();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (x2 == null) {
            x2 = System.currentTimeMillis();
        }
        super.channelRead(ctx, msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.channel().close();
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        while (true) {
            if (in.readableBytes() < ProtocolUtil.HEADER_LENGTH) return;
            int start = in.readerIndex();
            int upLimit = start + ProtocolUtil.FRAME_LENGTH_BLOCK;
            byte[] frameLengthBytes = new byte[ProtocolUtil.FRAME_LENGTH_BLOCK];
            for (int i = start; i < upLimit; ++i) {
                try {
                    frameLengthBytes[i - start] = in.getByte(i);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
            int frameLength = (int) ProtocolUtil.convertBytesToLong(frameLengthBytes);
            if (in.readableBytes() < frameLength) return;
            byte[] frameBytes = new byte[frameLength];
            in.readBytes(frameBytes);
            if (frameBytes[8] == ProtocolUtil.CONTENT_TYPE_TIME[0] && frameBytes[9] == ProtocolUtil.CONTENT_TYPE_TIME[1]) {
                byte[] timeBytes = new byte[8];
                System.arraycopy(frameBytes, ProtocolUtil.HEADER_LENGTH, timeBytes, 0, timeBytes.length);
                y1 = ProtocolUtil.convertBytesToLong(timeBytes);
                y2 = (long) ((double) (x2 - x1) / 2 + y1);
                EventBus.getDefault().post(new EventSyncHostTime(y2 - x2));
                ctx.close();
            }
        }
    }
}
